{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\n1. 针对有偏数据集（负样本对远大于正样本对）\\n除accuray指标外，还可以采用precision_score,recall_score,f1_score来更加精确的反应模型训练效果\\n\\n2. 在判断样本对是否是正样本对时，我们可以尝试使用不同的阈值来预测模型准确率\\ndef compute_accuracy(y_true, y_pred,threshold):\\n    pred = y_pred.ravel() < threshold\\n    print('pred:', pred)\\n    return np.mean(pred == y_true)\\n\\t\\n3. 以下代码将实现以下功能：\\na. 使用model.predict_generator进行结果预测\\nb. 尝试在不同的阈值下，绘制模型precision_score,recall_score,f1_score\\n\""
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''\n",
    "1. 针对有偏数据集（负样本对远大于正样本对）\n",
    "除accuray指标外，还可以采用precision_score,recall_score,f1_score来更加精确的反应模型训练效果\n",
    "\n",
    "2. 在判断样本对是否是正样本对时，我们可以尝试使用不同的阈值来预测模型准确率\n",
    "def compute_accuracy(y_true, y_pred,threshold):\n",
    "    pred = y_pred.ravel() < threshold\n",
    "    print('pred:', pred)\n",
    "    return np.mean(pred == y_true)\n",
    "\t\n",
    "3. 以下代码将实现以下功能：\n",
    "a. 使用model.predict_generator进行结果预测\n",
    "b. 尝试在不同的阈值下，绘制模型precision_score,recall_score,f1_score\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import cv2\n",
    "import csv\n",
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import random\n",
    "from keras import backend as K\n",
    "from keras.preprocessing.image import img_to_array\n",
    "from keras.optimizers import SGD,RMSprop\n",
    "from keras.models import Model, Sequential,load_model\n",
    "from keras.layers import Input,Concatenate, Add,Subtract,Lambda\n",
    "from keras.callbacks import EarlyStopping, ModelCheckpoint\n",
    "from keras.optimizers import Adam,RMSprop,SGD"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "#set GPU to memory-growth mode\n",
    "\n",
    "gpus = tf.config.experimental.list_physical_devices(device_type='GPU')\n",
    "for gpu in gpus:\n",
    "    tf.config.experimental.set_memory_growth(gpu, True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "#define threshold_train\n",
    "#images_paths='/root/tf-2.0/Siamese_Face_Detection/data/FaceV5_160_train.csv'\n",
    "#images_data=pd.read_csv(images_paths)[:50000]\n",
    "#images_data.to_csv('/root/tf-2.0/Siamese_Face_Detection/data/threshold_train.csv',index=None,header=None)\n",
    "\n",
    "train_threshold_path='/root/tf-2.0/Siamese_Face_Detection/data/threshold_train.csv'\n",
    "images_data=pd.read_csv(train_threshold_path,header=None)\n",
    "images_data.columns=['pair1','pair2','labels']\n",
    "labels=images_data['labels']\n",
    "#labels[:10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#define images generator\n",
    "\n",
    "def processImg(filename,h,w):\n",
    "    \"\"\"\n",
    "    :param filename: 图像的路径\n",
    "    :return: 返回的是归一化矩阵\n",
    "    \"\"\"\n",
    "    height=h\n",
    "    width=w\n",
    "\n",
    "    img = cv2.imread(filename)\n",
    "    img = cv2.resize(img, (height, width))\n",
    "    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n",
    "    img = img_to_array(img)\n",
    "    img /= 255.\n",
    "    return img\n",
    "\n",
    "def generator(imgs, batch_size,input_shape):\n",
    "    \"\"\"\n",
    "    自定义迭代器\n",
    "    :param imgs: 列表，每个包含一对图片矩阵\n",
    "    :param batch_size:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    h,w,c=input_shape\n",
    "    while 1:\n",
    "        li = imgs[:batch_size]\n",
    "        pairs = []\n",
    "        for i in li:\n",
    "            img1 = i[0]\n",
    "            img2 = i[1]\n",
    "            im1 = cv2.imread(img1)\n",
    "            im2 = cv2.imread(img2)\n",
    "            if im1 is None or im2 is None:\n",
    "                continue\n",
    "            img1 = processImg(img1,h=h,w=w)\n",
    "            img2 = processImg(img2,h=h,w=w)\n",
    "            pairs.append([img1, img2])\n",
    "        pairs = np.array(pairs)\n",
    "        yield [pairs[:, 0], pairs[:, 1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_shape=(160,160,3)\n",
    "batch_size=20\n",
    "\n",
    "rows_test=csv.reader(open(train_threshold_path, 'r'), delimiter=',')\n",
    "imgs_test = list(rows_test)\n",
    "steps=len(imgs_test)//batch_size\n",
    "## define image pair generator\n",
    "test_data=generator(imgs_test,batch_size,input_shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# calculate loss\n",
    "def contrastive_loss(y_true, y_pred):\n",
    "    margin = 1\n",
    "    square_pred = K.square(y_pred)\n",
    "    margin_square = K.square(K.maximum(margin - y_pred, 0))\n",
    "    return K.mean(y_true * square_pred + (1 - y_true) * margin_square)\n",
    "\n",
    "Siamese_softmax_model=load_model('/root/tf-2.0/Siamese_Face_Detection/h5/Siamese_softmax_02.h5',\n",
    "                                 custom_objects={'contrastive_loss':contrastive_loss})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2500/2500 [==============================] - 676s 270ms/step\n"
     ]
    }
   ],
   "source": [
    "y_pred=Siamese_softmax_model.predict_generator(test_data,steps=steps,verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.31549463] [1.8420728]\n"
     ]
    }
   ],
   "source": [
    "#y_predict=pd.DataFrame(y_pred)\n",
    "#y_predict.to_csv('/root/tf-2.0/Siamese_Face_Detection/data/predict.csv',header=None,index=None)\n",
    "\n",
    "min_threshold=min(y_pred)\n",
    "max_threshold=max(y_pred)\n",
    "print(min_threshold,max_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score,recall_score,f1_score\n",
    "import numpy as np\n",
    "\n",
    "y_true=list(labels)\n",
    "precision=[]\n",
    "recall=[]\n",
    "f1_score=[]\n",
    "accuracy=[]\n",
    "thresholds=np.arange(0.4,1.5,0.02)\n",
    "\n",
    "def compute_prediction(y_pred,threshold):\n",
    "    pred = y_pred.ravel() < threshold\n",
    "    #pred=int(pred)\n",
    "    return list(pred.astype(np.int32))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "for threshold in thresholds:\n",
    "    y_prediction=compute_prediction(y_pred,threshold)\n",
    "    p=precision_score(y_true,y_prediction)\n",
    "    r=recall_score(y_true,y_prediction)\n",
    "    f1=2*p*r/(p+r)\n",
    "    a=np.mean(np.array(y_prediction) == np.array(y_true))\n",
    "    precision.append(p)\n",
    "    recall.append(r)\n",
    "    f1_score.append(f1)\n",
    "    accuracy.append(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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aW3cuFGS9Pvvv1/z3Nu2bdPSpUsVGBioY8eOKTExUUFBQVq6dKmef/55ffzxx5o9e7Z27typH374QUFBQTp8+LDKli2rp59+WgcOHFCFChU0d+5c9ezZM29fEFGEAQB58O230rp10uuvF4wl07ITHBSs9qHtmScMv/HSSy9p4cKFkqTdu3dr9uzZioyMVI0aNSRJISEhkqSlS5fqvffeO/++smXLXvPc9913nwIDAyVJR48e1SOPPKLt27fLGKP09PTz533yyScVFBR00fUeeughzZ8/Xz179tTKlSv173//O8+fK0UYAJBr55ZM+/vfbSfxrKiaUVq0fZFSj6QqtEyo7TjwAzkZufWEr7/+WkuXLtXKlStVrFgxtW/fXo0aNTo/beFCjuPIZPMv4AufO3369EWvFS9e/PyfR4wYoQ4dOmjhwoVKTU1V+z9+rXSl8/bs2VN//vOfVaRIEd13333ni3JeMEcYAJAru3dLn3wiPfaYdMHPtgLpwu2WgYLs6NGjKlu2rIoVK6YtW7bou+++05kzZ5SQkKCdO3dK0vmpEVFRUfrXv/51/r3npkbccMMNSk5OVlZW1vmR5Std66abbpIkzZs37/zzUVFReu21187fUHfuepUrV1blypX14osvnp93nFcUYQBArrz2mmuO8NNP207ieXXK11GVUlUowijw7rjjDmVkZKhhw4YaMWKEIiIiVKFCBc2ePVv33nuvGjVqpG7dukmShg8frt9//10NGjRQo0aNtGzZMknShAkTdNddd+n2229XpUqVrnitQYMGaejQoWrdurUyM/+3e+M//vEPVatWTQ0bNlSjRo307rvvnn/t73//u6pWrap69eq55fM1juO45UTXKzw83ElKSrJybQBA3pw6JVWtKrVt69pIwx889tlj+mTLJzow8ICCAphZCPdLTk5W3bp1bcfwaX369FGTJk302GOPXfGY7L6Oxpi1juOEX3osI8IAgOv23nsFe8m07ESFRenI6SNK2scgDmBDs2bNtGHDBj344INuO2eOirAx5g5jzFZjzA5jzJCrHPdXY4xjjLmscQMACoZzS6bVry916GA7jfd0qtlJRobpEYAla9euVWJiooKDg912zmsWYWNMoKSXJf1JUj1J3Y0xl03MMMaUlPSMpFVuSwcA8DnLl0s//OAaDS6oS6Zlp1yxcgqvHE4RhkfZmrJaUFzv1y8nI8ItJO1wHOcnx3HOSnpP0t3ZHDdG0iRJp7N5DQBQQMyaJZUpI7nxt5P5RlRYlL7b852Onj5qOwoKoCJFiujQoUOU4VxyHEeHDh1SkSJFcvyenMz2v0nS7gse75HU8sIDjDFNJFV1HOcLY0xMjq8OAMhXfv5Z+vhjqV+/gr9kWnaiwqI09puxWpa6TPfUucd2HBQwVapU0Z49e3TgwAHbUfKtIkWKqEqVKjk+PidFOLtffJ3/p4oxJkDSdEk9rnkiY56Q9IQkVatWLWcJAQA+Y9o013SIZ56xncSOiCoRKlG4hGJTYinCcLtChQqd370N3pGTqRF7JFW94HEVSfsueFxSUgNJXxtjUiVFSPo8uxvmHMeZ7ThOuOM44RUqVMh9agCA1x06JL3xhvS3v0n+OpZROLCwOoR2YJ4wUEDkpAivkVTLGFPDGFNY0gOSPj/3ouM4Rx3HKe84TqjjOKGSvpPUxXEc1pcBgALkX/+STp6UBg2yncSuqLAopfyeopTDKbajAMijaxZhx3EyJPWRtFhSsqQPHMf50Rgz2hjTxdMBAQD2paW5bpK76y7Xsmn+jO2WgYIjR1vjOI6zSNKiS54beYVj2+c9FgDAl8yZ45oaMXiw7ST21Qqppeqlqyv2p1g91fwp23EA5AE7ywEArio9XZoyRWrdWmrTxnYa+4wxigqLUvzOeKVnptuOAyAPKMIAgKt6/33XsmmMBv9PVFiUjp05ptV7V9uOAiAPKMIAgCtyHGnSJKlePen//s92Gt9xe43bFWACmCcM5HMUYQDAFf33v9LGja6VIgL4iXFeSNEQNa/cXLE/UYSB/IxvawCAK5owQapaVere3XYS3xMdFq3Ve1fr91O/244CIJcowgCAbK1cKX3zjTRggFS4sO00vicqLEpZTpbid8bbjgIglyjCAIBsTZwolS0r/eMftpP4phY3tVCp4FLMEwbysRytIwwA8C+bN0uffSaNGCGVKGE7jW8qFFhIt9e4XV9s/0Kz1862HUfhlcPVtFJT2zGAfIUiDAC4zOTJUtGiUt++tpP4tq51uurTLZ+q1xe9bEdRcGCwtvbZquplqtuOAuQbFGEAwEX27JH+8x+pVy+pQgXbaXzbw40e1h0336GMrAyrOQ6ePKiWb7bUsPhhmn/vfKtZgPyEIgwAuMj06VJWlvTcc7aT5A8Vi1e0HUGVS1ZW/4j+Gv/tePWP6K9mlZvZjgTkC9wsBwA47/Bh6fXXpQcekEJDbafB9RjcerDKFyuvmCUxchzHdhwgX6AIAwDOe+UVKS3NtYEG8pfSRUprVLtR+jr1a325/UvbcYB8gSIMAJAknTolvfSS9Kc/SQ0b2k6D3Hii2ROqXa62Bi0ZZH3eMpAfUIQBAJKkuXOlAwekwYNtJ0FuFQospAkdJyj5YLLm/DDHdhzA51GEAQDKyHAtmRYRIUVG2k6DvLinzj1qU62NRi4bqeNnjtuOA/g0ijAAQB9+KKWmukaDjbGdBnlhjNGUzlO0P22/pqyYYjsO4NMowgDg5xzHtZ1ynTpSly6208AdWlZpqfvr368pK6do3/F9tuMAPosiDAB+LjZWWr9eGjhQCuCnQoExvuN4pWema+SykbajAD6Lb3kA4OcmTZIqV5b+/nfbSeBONcvWVJ8WfTR33Vxt+m2T7TiAT6IIA4AfS0qS4uOl/v2l4GDbaeBuwyOHq1RwKQ1awsLQQHYowgDgxyZPlkqVkp54wnYSeEJI0RANbztc/93xXy39aantOIDPoQgDgJ9KSZE++kh66ilXGUbB1KdFH4WWCVVMbIwyszJtxwF8CkUYAPzUtGlSUJD0zDO2k8CTgoOCNe72cVq/f73mb5hvOw7gUyjCAOCHDhyQ5syRHnrIdaMcCrZuDbqpeeXmGr5suE6ln7IdB/AZFGEA8EP/+pd0+rQUE2M7CbwhwARoStQU7Tm2RzO+m2E7DuAzKMIA4GfS0lxF+O67XZtowD9EVo/U3bfcrfHfjtdvab/ZjgP4BIowAPiZOXOkw4elQayo5Xcmdpqok+knNTphtO0ogE8wjuNYuXB4eLiTlJRk5doA4K8yMqSbb5aqVJG+/dZ2GtjQ+8veejXpVQWaQI+c/4lmT+iV/3vFI+cGcssYs9ZxnPBLnw+yEQYAYMeHH0q7dkkvvWQ7CWyZ0GmCqpeuruNnj7v93D8e+FGvJr2qv9/6d7Wu1trt5wfcjRFhAPATjiM1beq6Se7HH6UAJsfBzdLOpqnWrFoKLROq5Y8ulzHGdiRA0pVHhPk2CAB+YulSad06aeBASjA8o3jh4hrTYYxW7lmpj5M/th0HuCa+FQKAn5g0SapUSfr7320nQUHWo3EPNajYQEOWDtHZzLO24wBXRREGAD/w/feuEeF+/aTgYNtpUJAFBgRqcufJSvk9Ra+uedV2HOCqKMIA4AcmT5ZKlpR69bKdBP4gOixanWp20ujE0Tpy+ojtOMAVUYQBoIDbuVP64APpySel0qVtp4E/MMZocufJ+v3U7xr/zXjbcYAroggDQAE3bZoUGOiaFgF4S+MbG+vhRg9r5qqZ2nVkl+04QLYowgBQgB08KL31lvTQQ1LlyrbTwN+8ePuLMsZoWPww21GAbFGEAaAAe/ll6dQpKSbGdhL4oyqlqqh/RH/9Z+N/tHbfWttxgMtQhAGggDp5Upo1S+rSRapb13Ya+KvBrQerfLHyGrhkoGxt4gVcCUUYAAqouXOlQ4ekQYNsJ4E/K12ktEa1G6Vlqcu0aPsi23GAi7DFMgAUQBkZUu3arg00li+3nQb+Lj0zXQ1ebaBAE6gNT21QUECQ7UjwM1faYpn/EwF4VVyctGyZ7RQF3549rmXTpk+3nQSQCgUW0oSOE3TvB/dqzg9z9ESzJ2xHAiQxIgzAy0JDpV27XMt5wbOaN3eNBgcwCQ4+wHEctZ3bVjsO79COZ3aoROEStiPBjzAiDMC6Xbtc/82cKT3zjO00ALzJGKOpUVMV8VaEpqyYolHtR9mOBHCzHADvSUx0fWzXzm4OAHa0rNJS99e/X5NXTNYvx3+xHQegCAPwnsREqUwZ6dZbbScBYMv4juOVnpmukctG2o4CUIQBeE9CgtS2LXNWAX9Ws2xNPd38ac1ZN0c//vaj7Tjwc8wRBuAVv/wibd8u9eplOwkA24ZHDte89fP08KcPq3319rbjIA/+Uu8valW1le0YuUYRBuAV5+YHR0bazQHAvnLFymlG9Az1W9xP2w5tsx0HuXQm44zmrZ+nlGdSVKZIGdtxcoUiDMArEhKkkiWlJk1sJwHgCx5p/IgeafyI7RjIg/W/rleT15to3DfjNKnzJNtxcoWZegC8IjFRat1aCuKf3wBQIDS6sZEeafyIZq6aqdQjqbbj5ApFGIDHHTwo/fgj0yIAoKAZ02GMAk2ghsUPsx0lVyjCADzum29cH1k/GAAKliqlqmjAbQP07sZ3lbQv/+0YTBEG4HEJCVLRolL4ZZtbAgDyu0GtB6lCsQqKiY2R4zi241wXijAAj0tIkG67TSpc2HYSAIC7lQoupRfav6CEXQn6f9v+n+0414UiDMCjjhyR1q9nfjAAFGT/aPoP3VLuFg1aMkjpmem24+QYRRiAR337reQ4zA8GgIKsUGAhTeo8SVsPbdWb379pO06OUYQBeFRiomtKRMuWtpMAADzpz7X/rMjqkRqVMErHzhyzHSdHKMIAPCohQWrRwnWzHACg4DLGaErnKfot7TdNWp4/NtigCAPwmOPHpbVrmRYBAP6i+U3N1b1Bd01bOU17ju2xHeeaKMIAPGblSikzkxvlAMCfjOs4TplOpkYsG2E7yjVRhAF4TEKCFBgotWplOwkAwFtCy4TqmRbP6O11b2v9r+ttx7kqijAAj0lMdG2iUaKE7SQAAG96vu3zKlu0rAYuGWg7ylVRhAF4xKlT0urVTIsAAH9UtmhZjYgcoSU/LdHiHYttx7kiijAAj1i1Sjp7lhvlAMBf9W7eW2FlwxSzJEaZWZm242SLIgzAIxISJGOk1q1tJwEA2FA4sLDGdxyvTb9t0tvr37YdJ1sUYQAekZAgNW4slSljOwkAwJa/1vurIqpEaHj8cKWdTbMd5zIUYQBud/asa+k05gcDgH8zxmhq1FT9cuIXTV051Xacy1CEAbjdmjXS6dPMDwYASK2qttJf6v5Fk5ZP0sGTB23HuUiQ7QAACp7ERNfHtm3t5gAA+IYJnSbo4UYPq1zRcrajXIQiDMDtEhKk+vWl8uVtJwEA+IKbQ27WzSE3245xGaZGAHCrjAxp+XKmRQAAfB9FGIBb/fCDdOIEN8oBAHwfRRiAWyUkuD4yIgwA8HUUYQBulZgo1a4t3Xij7SQAAFwdRRiA22RmSt98w7QIAED+QBEG4DabNklHjjAtAgCQP1CEAbjNufnBjAgDAPIDijAAt0lIkEJDpWrVbCcBAODaKMIA3MJxXDfKMRoMAMgvKMIA3CI5WTp4kPnBAID8gyIMwC0SE10fKcIAgPyCIgzALRISpMqVpZo1bScBACBnKMIA8sxxXEW4XTvJGNtpAADIGYowgDxLSZF++YUb5QAA+QtFGECenVs/mPnBAID8JEdF2BhzhzFmqzFmhzFmSDavDzDGbDbGbDDGxBljqrs/KgBflZgoVagg1aljOwkAADl3zSJsjAmU9LKkP0mqJ6m7MabeJYf9ICnccZyGkj6SNMndQQH4roQE17QI5gcDAPKTnIwIt5C0w3GcnxzHOSvpPUl3X3iA4zjLHMc5+cfD7yRVcW9MAL5q1Spp1y6pY0fbSQAAuD45KcI3Sdp9weM9fzx3JY9J+m92LxhjnjDGJBljkg4cOJDzlAB81rhxUkiI9NBDtpMAAHB9clKEs/tlp5PtgcY8KClc0uTsXnccZ7bjOOGO44RXqFAh5ykB+KSNG6XPP5eefVYqUcJ2GgAArk9QDo7ZI6nqBY+rSNp36UHGmE6Shklq5zjOGffEA+DLxo93FeA+fWwnAQDg+uVkRHiNpFrGmBrGmMKSHpD0+YUHGGOaSHpdUhfHcX5zf0wAvmbHDun996XevV1TIwAAyG+uWYQdx8mQ1EfSYknJkj5wHOdHY8xoY0yXPw6bLKmEpA+NMeuMMZ9f4XQACoiJE6VChaT+/W0nAQAgd3IyNUKO4yyStOiS50Ze8OdObs4FwIft3i29/bb0xBPSjTfaTgMAQO6wsxyA6zZ1quQ40sCBtpMAAJB7FGEA1+W336TZs6UHH5Sqs4ckACAfowgDuC4zZ0qnT0tDLttsHQCA/IUiDCDHjhyR/vUv6a9/lW65xXYaAADyhiIMIMdeeUU6dkwaOtR2EgAA8o4iDCBH0tKk6dOlO++UmjSxnQYAgLyjCAPIkTfflA4elJ5/3nYSAADcgyIM4JrOnJEmT5batZNat7adBgAA98jRhhoA/Ns770h790pz5thOAgCA+zAiDOCqMjKkCROk8HCpc2fbaQAAcB9GhAFc1YcfSikp0iefSMbYTgMAgPswIgzgirKypHHjpHr1pLvvtp0GAAD3YkQYwBV98YW0aZNrjnAA/2wGABQw/GgDkC3HkcaOlWrUkB54wHYaAADcjxFhANmKj5dWr5Zee00K4jsFAKAAYkQYQLbGjpUqVZJ69LCdBAAAz2CcB8BlvvtOWrZMmjpVCg62nQYAAM9gRBjAZSZMkEJCpCeesJ0EAADPoQgDuEhysvTZZ1KfPlKJErbTAADgORRhABeZPFkqWlTq29d2EgAAPIsiDOC8PXuk+fOlxx6Type3nQYAAM+iCAM4b/p0125yzz1nOwkAAJ5HEQYgSTp8WJo927V5Rmio7TQAAHgeRRiAJOmVV6QTJ6RBg2wnAQDAO1hHGIBOnZJeekn605+khg1tpwGQF46TqaysM+f/c5wz2TxO99TV5TiZcpx0Oc5ZZWWdleOk///27j44jvq+4/j7e6d7lOQHJD8oBj/WLg/GlpmUAVrKY11wE5yW0JYADcEp0xBKWh4KZdKQkofBHUoJgw0FYojjFpq0hZKGBEIDoYNxCQOY2Bh7sGUCWMiyEcb26aR7+PWPvbMk0MPJ1t3eaT+vmZ3d21vdfk/fk+5zu3u7h8bevL77IFemOqQSnHNArtDfgb0dbOxcniVLnvW77AEUhEWEBx+Ezk646Sa/KxE5fLlcit7ednp62untfY/e3vZ+w3uF4FWavjCXLYy9ae+NPvOR+6ojzBUDsMKlVJZhFiUUipY0ds5hZn4XfYiCsEjAZbNw++1wyilw+ul+VyPjhXM5urvbSKXeIJPZU9gK2VvYIjlw7G0tKo6zo1hHlkxmdyH4tpPLffixZczqiESmEY1OJxxOjOIZhAiFEoRCEczqMIsUBm/am1+8HQaq4Y09RCgUOzSYxYa8bRahXDWbhQuhJ9IvAEUGnVc9vzs5XNUUag+HgrBIwP3wh9DWBnfcATX++ss9/AAADTdJREFU/0x8kMt1k0ptJZXaQir1RmG8hVRqG84NvwXWC0exQjDyxl6wLPWFGCIanUpDwyKi0d8nGp1ONNpCLNZCNOoNkUgTZvo6jIgMTkFYJMCcg5Ur4dhj4YIL/K5GqlUud5Du7jbS6Z2k022k022HQm86/RbgCkuGiMfnUF9/HEcddR7J5HEkk8cSjbYMCLzFXaS1viVJRGqfgrBIgD31FGzcCGvWQEgbzQIrn88WQu4O0um2j4XeTKZzwPKhUIJk8jeZMOEUpk//AsnksSSTx5FIzCccjvv0LERERk9BWCTAVq6EGTPgkkv8rkQqwbk86fSvSaU2c/Dgpn7DFpzrObScWYRYbCaJxByamz9DPD6HeHwOicQc4vHZRCJTtTVXRMYFBWGRgHrxRXjmGe+LctFo5dbb27uHnp63K7fCAMtk9g4IvKnUZnK5A4fuj8WOpr5+IZMnn0syeTyJxDzi8TnEYp8ofIlJRGR8UxAWCaiVK2HSJLjyyvKvy7k8XV0/Y9eu+9m7979GdWYAOXJ1dU00NJzI9OmXU1+/kPr6hSSTJxCJTPK7NBERXykIiwTQ1q3w6KNw883Q2Fi+9fT0vEt7+xra279LT89b1NU1MWPGNUyceLp2rVdAONxIff0JOpRBRGQICsIiAXT77RCLwTXXjP1j5/NZ3n//CdrbH2Dv3h8DeSZNOod581bS3PwZQqHY2K9URETkMCgIiwTMrl2wdi2sWAFTp47d43Z37+S9975Le/saent3EY1OZ+bMG2lpWUEiMW/sViQiIjJGFIRFAubOO72ryV1//ZE/VjZ7gD17HqOjYy1dXU8DcNRR59HScjdNTZ8iFIoc+UpERETKREFYJEA++ADuvRcuugjmzj28x8jns3R1/YyOjnXs2fMY+XyKWGwWs2Z9jZaWK4jHZ45t0SIiImWiICwSIPfcA/v3w403ju7nnHPs3/8SHR3r2L37ETKZ3dTVTWbatMuYNu1SJk48TZexFRGRmqMgLBIQ6TR85zuwdCksWVLaz3R376Cj41/o6FhHd/c2zGI0NX2KadMupanpfH3xTUREapqCsEgV6e6GG26Arq6xf+yODm8oZWvw++8/zc6dt/Dhh+sBmDTpTGbO/Buamy/UuWdFRGTcUBAWqSL33w+rVnnH74bKcKTBxRfDWWcNfX9PTzvbt1/L7t2PEI/PYe7c25g69WId9ysiIuOSgrBIlUinvau9nXEGPPtsZdftXI53311NW9tXyefTzJp1CzNn3kQ4HK9sISIiIhWkICxSJdas6TvHbyV9+OGLbNv2Fxw48AqTJ/8e8+evIpmcX9kiREREfKAgLFIFenvhttvgtNPg7LMrs85Mpou2tpvZteufiUanc/zx/8aUKRfpUrwiIhIYCsIiVeB734O33/aOES53DnXO0dHxfbZvv55MZi9HH/0VZs/+e+rqJpR3xSIiIlVGQVjEZ5kMfPvbcPLJ3qnNyungwdfZtu0q9u37BRMmnMKiRU/R2Nha3pWKiIhUKQVhEZ+tWwc7d8Ldd0M6vYNt264im9075utxznHw4EbC4UYWLLiPlpYVugiGiIgEmoKwiI+yWfjWt+Ckk+DMM7fyyitnk893M2HCqWVZ38SJX2LWrL8jGp1SlscXERGpJQrCIj56+GHYvh0ef3wTr756LuBobf0FDQ0n+l2aiIjIuBesIPyrX8G11/pdhQRRPA4LF8LixdDaCvPnkyPMN78Jy5a9zOTJSzGLsXjx/1Bff6zf1YqIiARCsIJwPg+plN9VSBB1dMBPf+odCwGQSPCDT1xHOPoHXPeVcwlnG2hd+BMSCsEiIiIVE6wgvHgxPP+831VIUPX0wJYtsHEj+Vc28sj6hdzx9XNIdqZovfYg8c5WmDcPTjwRGhrKV4eZd/3mkcahEESjHx9iscHn19d7dTc0DJyOxcp/TjipLOe80510d/cNqdTQ02beXpH+QyLx8XnxuPdaKvX14pz34TKb9eoZadq50p9jJOK9fhsb+8Z1wXrLFAkC/VWLVEos5h0W0drKjyY9zZfOu4C6ulksOXUtsQfeg1df9YbNm70rbJSDc31DPj/8OJfzQkRvb9+W7MMRDveF4uIQjY7dc5Kh5fNeH7PZgeOhpkt5XeTzfdNBE49/PBw3NkIyWT0f9oofYsPhvumhhnLV3P/D9GBD/9rMqud3J4dvsA0qg80Lh+Hqq/2udgAFYZEK6+z8McnkhXR0LODCC58mlpgKc4FPf9rv0obWPxQPNvT0eFv+DhwYejh40Bvv3+89lpSfmbcVMxz2huL0YPOK4aTUPQbFrbqJhBcEi9OD3TaDdLpv6O4eeLv//NF+CIxEvOdQVzf8dPH5laq3t+/1Whz3ny6Ou7rg3XdHV3O5FD/k5nJ9H1gGG4r3l7OOkdZdzvVL9QqFFIRFgqyz81E2bfoTduxYRGPjkyQSTX6XVJpiUIrH/a5ERMaLYmCW2jbcnsbB5lUZBWGRCunoeJgtWy5j586TWbXqCV5+eZLfJYmI+Ke4q1zERwrCIhXQ3v4gW7euIJf7Xb785R+xenWjvncjIiLis0C9Fe/bt4FNm5b7XYYEUCazm8mTl3LVVY8ybVqSSy7xuyIREREJVBCORJqZMuWP/C5DAiganc4bb9zI+vVx7rvP++6OiIiI+CtQQTiZ/A0WLLjH7zIkgJyDz30OjjkGPv95v6sRERERCFgQFvHLz38OL7wAq1frFLoiIiLVYhQnVRSRw3XrrTBjBlxxhd+ViIiISFGgtghv2gTXX+93FRI0mQw89xzcdZd3cTkRERGpDoEKwtksfPCB31VIEC1fDl/8ot9ViIiISH+BCsKtrbBhg99ViIiIiEg10DHCIiIiIhJICsIiIiIiEkgKwiIiIiISSArCIiIiIhJICsIiIiIiEkgKwiIiIiISSArCIiIiIhJICsIiIiIiEkgKwiIiIiISSArCIiIiIhJICsIiIiIiEkgKwiIiIiISSArCIiIiIhJICsIiIiIiEkgKwiIiIiISSArCIiIiIhJICsIiIiIiEkgKwiIiIiISSOac82fFZp3AW76sHJqBPT6tW46c+lf71MPapx7WNvWv9qmHozPLOTflozN9C8J+MrOXnHOf9LsOOTzqX+1TD2ufeljb1L/apx6ODR0aISIiIiKBpCAsIiIiIoEU1CB8n98FyBFR/2qfelj71MPapv7VPvVwDATyGGERERERkaBuERYRERGRgBu3QdjMzjOzrWb2ppndNMxynzUzZ2b65mWVKaWHZvbHZva6mW02s3+tdI0yvJF6aGYzzewZM3vFzF4zs2V+1CmDM7M1ZrbbzDYNcb+Z2V2F/r5mZidVukYZXgk9vKTQu9fMbL2ZLa50jTK0kfrXb7nfMrOcmX22UrWNF+MyCJtZGFgFnA8cD1xsZscPslwjcA3wf5WtUEZSSg/NbD7wt8BvO+dOAP6q4oXKkEr8O/wq8APn3BLgT4HVla1SRvAQcN4w958PzC8MVwL3VKAmGZ2HGL6HbcAZzrlFwDfQcafV5iGG71/xf+1K4MlKFDTejMsgDJwMvOmc2+Gc6wUeAZYPstw3gH8A0pUsTkpSSg//HFjlnOsCcM7trnCNMrxSeuiACYXpicCuCtYnI3DOPQe8P8wiy4G1zrMBmGRmLZWpTkoxUg+dc+uL/0OBDcDRFSlMSlLC3yDAXwL/Aeg98DCM1yA8A3i73+13CvMOMbMlwDHOuf+uZGFSshF7CCwAFpjZ82a2wcyG/dQsFVdKD78OXGpm7wBP4P1Dl9pRSo+ldqwAfuJ3EVI6M5sB/CFwr9+11Ko6vwsoExtk3qHTY5hZCPgn4PJKFSSjNmwPC+rwdsmeibcV43/NbKFz7oMy1yalKaWHFwMPOef+0cxOBb5f6GG+/OXJGCilx1IDzOwsvCD8O37XIqNyJ3Cjcy5nNtifo4xkvAbhd4Bj+t0+moG7XBuBhcCzhRfOdOBxM7vAOfdSxaqU4YzUw+IyG5xzGaDNzLbiBeNfVqZEGUEpPVxB4fg359wLZhYHmtEuvlpRSo+lypnZIuAB4Hzn3F6/65FR+STwSCHLNAPLzCzrnHvM37Jqx3g9NOKXwHwzm2NmUbwv4TxevNM5t8851+ycm+2cm413XJRCcHUZtocFjwFnAZhZM96hEjsqWqUMp5Qe/ho4B8DMjgPiQGdFq5Qj8TjwZ4WzR5wC7HPOtftdlJTOzGYC/wlc5pzb5nc9MjrOuTn9ssy/A1cpBI/OuNwi7JzLmtnVeN+gDANrnHObzexW4CXn3EffjKXKlNjDJ4GlZvY6kANu0NaM6lFiD68D7jezv8bbpX6501V+qoaZPYx36FFz4TjuW4AIgHPuXrzjupcBbwIp4Av+VCpDKaGHXwOagNWFrYpZ55xOJ1olSuifHCFdWU5EREREAmm8HhohIiIiIjIsBWERERERCSQFYREREREJJAVhEREREQkkBWERERERCSQFYREREREJJAVhEREREQkkBWERERERCaT/B8Ho7frJSQAgAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 864x576 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "#绘制准确率，召回率，F1_score,accuracy\n",
    "plt.figure(figsize=(12,8))\n",
    "plt.plot(thresholds,precision,'r',label='precision')\n",
    "plt.plot(thresholds,recall,'b',label='recall')\n",
    "plt.plot(thresholds,f1_score,'y',label='f1_score')\n",
    "plt.plot(thresholds,accuracy,'g',label='accuracy')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
